﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Xml;
using System.Net;
using Microsoft.VisualBasic;

namespace FSD_2_Config_Editor
{
    public partial class Form1 : Form
    {
        public string xmlLocation = null;
        public static string DriveSelection = "/hdd1/fsd2data/", ftpPassword = "xbox", ftpUserID = "xbox", ftpServerIP = "192.168.1.1";
        public static int Port = 21;
        string Region1;
        public bool DownloadComp = false, UploadComp = false;
        int NTP,fanSpeed, SelectedIndex = 0;

        //bool isDirty;

        struct GamePath
        {
            public string Path;
            public string Retail;
            public string DevKit;
        };

         GamePath[] Game = new GamePath[30];

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            this.Text = "FSD2 Config Editor " + this.ProductVersion.ToString().Remove(5, 2);
            RegioncomboBox.SelectedIndex = 0;
            NTPcomboBox.SelectedIndex = 0;
            FancomboBox.SelectedIndex = 0;
            RetailcomboBox.SelectedIndex = 5;
            DevkitcomboBox.SelectedIndex = 5;

            try
            {
                DataTable dt = new DataTable();
                using (TextReader tr = File.OpenText("settings.ini"))
                {
                    string line;

                    while ((line = tr.ReadLine()) != null)
                    {
                        string[] items = line.Split('=');
                        if (dt.Columns.Count == 0)
                        {
                            // Create the data columns for the data table based on the number of items
                            // on the first line of the file
                            for (int i = 0; i < items.Length; i++)
                                dt.Columns.Add(new DataColumn("Column" + i, typeof(string)));
                        }
                        dt.Rows.Add(items);
                    }


                        for (int i = 0; i < dt.Rows[0].Table.Rows.Count; i++)
                        {
                            if (dt.Rows[0].Table.Rows[i].ItemArray[0].ToString().Contains("ip address"))
                            {
                                ftpServerIP = dt.Rows[0].Table.Rows[i].ItemArray[1].ToString().Remove(0, 1);

                            }
                            else if (dt.Rows[0].Table.Rows[i].ItemArray[0].ToString().Contains("username "))
                            {
                                ftpUserID = dt.Rows[0].Table.Rows[i].ItemArray[1].ToString().Remove(0, 1);
                            }
                            else if (dt.Rows[0].Table.Rows[i].ItemArray[0].ToString().Contains("pass"))
                            {
                                ftpPassword = dt.Rows[0].Table.Rows[i].ItemArray[1].ToString().Remove(0, 1);
                            }
                            else if (dt.Rows[0].Table.Rows[i].ItemArray[0].ToString().Contains("port"))
                            {
                                Port = int.Parse(dt.Rows[0].Table.Rows[i].ItemArray[1].ToString().Remove(0, 1));
                            }
                            else if (dt.Rows[0].Table.Rows[i].ItemArray[0].ToString().Contains("path"))
                            {
                                DriveSelection = dt.Rows[0].Table.Rows[i].ItemArray[1].ToString().Remove(0, 1);
                            }
                           
                    }
                }
            }
            catch (Exception ex)
            {

            }
        }

        private void Openbutton_Click(object sender, EventArgs e)
        {
            //Open fsd2config.xml
            try
            {
                openFileDialog1.FileName = "fsd2config.xml";
                if (openFileDialog1.ShowDialog() == DialogResult.OK)
                {
                    PathscomboBox.Items.Clear();

                    xmlLocation = openFileDialog1.FileName;
                    //MessageBox.Show(xmlLocation);

                    OpenFile(xmlLocation);
                    
                    
                }

            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, ex.Source, MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void Addbutton_Click(object sender, EventArgs e)
        {
            try
            {
                if (PathscomboBox.Text != "")
                {
                    
                    int i = 0;

                    if (PathscomboBox.Items.Count != 0)
                    {
                        i = PathscomboBox.Items.Count - 1;
                    }

                    //Validate Path
                    if ((PathscomboBox.Text.ToUpper().StartsWith("HDD1")) || (PathscomboBox.Text.ToUpper().StartsWith("USB")))
                    {
                        Game[i].Path = PathscomboBox.Text;
                        Game[i].Retail = RetailcomboBox.SelectedItem.ToString();
                        Game[i].DevKit = DevkitcomboBox.SelectedItem.ToString();
                        //MessageBox.Show(Game[i].DevKit + " " + Game[i].Path + " " + Game[i].Retail);
                        PathscomboBox.Items.Add(Game[i].Path);
                    }
                    else
                    {                     
                        throw new System.Exception("Path is not valid, use hdd1, usb0, usb1 or usb 2");
                    }

                }
                else
                {
                    throw new System.Exception("Please enter a path");
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, ex.Source, MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void PathscomboBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            SelectedIndex = PathscomboBox.SelectedIndex;
            int i = PathscomboBox.SelectedIndex;
            bool RFound = false, DFound = false;
            for (int l = 0; l < RetailcomboBox.Items.Count; l++ )
            {
                if (RetailcomboBox.Items[l].ToString() == Game[i].Retail)
                {
                    RetailcomboBox.SelectedIndex = l;
                    RFound = true;
                }
                if (DevkitcomboBox.Items[l].ToString() == Game[i].DevKit)
                {
                    DevkitcomboBox.SelectedIndex = l;
                    DFound = true;
                }

            }
            if (RFound == false)
            {
                RetailcomboBox.SelectedIndex = 5;
            }
            if (DFound == false)
            {
                DevkitcomboBox.SelectedIndex = 5;
            }
        }

        private void Removebutton_Click(object sender, EventArgs e)
        {
            try
            {
                int i = PathscomboBox.SelectedIndex;
                if (i != -1)
                {
                    PathscomboBox.Items.RemoveAt(i);
                    RetailcomboBox.SelectedIndex = 5;
                    DevkitcomboBox.SelectedIndex = 5;
                }
                else
                {
                    throw new System.Exception("No path was selected");
                }
            }
            catch(Exception ex)
            {
                MessageBox.Show(ex.Message, ex.Source, MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void Editbutton_Click(object sender, EventArgs e)
        {
            try
            {
                int i = SelectedIndex;
                if (i != -1)
                {
                    
                    
                    Game[i].Retail = RetailcomboBox.Items[RetailcomboBox.SelectedIndex].ToString();
                    Game[i].DevKit = DevkitcomboBox.Items[DevkitcomboBox.SelectedIndex].ToString();
                    PathscomboBox.Items[i] = PathscomboBox.Text;
                    Game[i].Path = PathscomboBox.Items[i].ToString();
                    PathscomboBox.SelectedIndex = i;
                }
                else
                {
                    throw new System.Exception("No path was selected");
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, ex.Source, MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void Savebutton_Click(object sender, EventArgs e)
        {
            //Save fsd2config.xml
            try
            {
                saveFileDialog1.FileName = "fsd2config.xml";
                if (saveFileDialog1.ShowDialog() == DialogResult.OK)
                {
                    string saveLocation = saveFileDialog1.FileName;

                    WriteFile(saveLocation);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, ex.Source, MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void WriteFile(string saveLocation)
        {
            //Got a bit lazy here. will write better code later
            String TextToWrite = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" + Environment.NewLine
                + "<config>" + Environment.NewLine + "	<locale>" + Region1 + "</locale>" + Environment.NewLine
                + "	<paths>" + Environment.NewLine
                + "		<!--	Retail and devkit attributes are used to configure the tab on which" + Environment.NewLine
                + "			the title is displayed if it is a retail or devkit executable." + Environment.NewLine
                + "			Options are: 360, HOMEBREW, EMULATOR and XBOX1 (can be left blank)." + Environment.NewLine
                + "			Example: <path retail='360' devkit='EMULATOR'>hdd1:\\emulators</path> -->"
                + Environment.NewLine;

            for (int i = 0; i < Game.Count(); i++)
            {
                if (Game[i].Path != null)
                {
                    TextToWrite += "		<path retail='" + Game[i].Retail + "' devkit='";

                    if (Game[i].DevKit == "[NONE]")
                    {
                        TextToWrite += "'>";
                    }
                    else
                    {
                        TextToWrite += Game[i].DevKit + "'>";
                    }

                    if (Game[i].Retail == "[NONE]")
                    {
                        TextToWrite += "</path>" + Environment.NewLine;
                    }
                    else
                    {
                        TextToWrite += Game[i].Path + "</path>" + Environment.NewLine;
                    }
                }
            }
            TextToWrite += "	</paths>" + Environment.NewLine + "	<feeds>" + Environment.NewLine + "	</feeds>"
                + Environment.NewLine + "	<skin>Default.xzp</skin>" + Environment.NewLine
                + "	<Music Path='game:\\Music\\'MUST be in GAME:\\  />" + Environment.NewLine + "	<Video Path='' />"
                + Environment.NewLine + "	<DVDCopy 360Path='' OrigPath=''/>" + Environment.NewLine
                + "	<weather location='undefined' />" + Environment.NewLine
                + "	<display horizoverscan='0' vertoverscan='0' horizdisplacement='0' vertdisplacement='0' letterbox='0'/>"
                + Environment.NewLine + "	<ftp xboxip='0.0.0.0' port='21' username='xbox' password='xbox' />"
                + Environment.NewLine + "	<gamelistopt background='1' preview='1' semitransparent='0' covers='0' />"
                + Environment.NewLine + "	<mainscreenopt tempstatus='1' diskstatus='1' celsius='1' parent='0' showip='1' showstatus='1' showavatar='1' />"
                + Environment.NewLine + "	<moreoptions fanspeed='";
            TextToWrite += fanSpeed + "' ledformat='0' />" + Environment.NewLine + "	<timeformat time='1' date='0' ntponstartup='";
            TextToWrite += NTP + "' />" + Environment.NewLine + "	<autoupdater ondash='1' onskin='1' onplugin='0' onbeta='1' installer='0' />"
                + Environment.NewLine + "	<Version XEX='0' />" + Environment.NewLine + "</config>";

            File.WriteAllText(saveLocation, TextToWrite, Encoding.UTF8);
        }

        private void RegioncomboBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            Region1 = RegioncomboBox.SelectedItem.ToString();
        }

        private void NTPcomboBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            NTP = NTPcomboBox.SelectedIndex;
        }

        private void FancomboBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (FancomboBox.SelectedIndex == 0)
            {
                fanSpeed = 40;
            }
            else
            {
                fanSpeed = Convert.ToInt32(FancomboBox.SelectedItem.ToString().Replace("%", ""));
            }
        }

        private void FTPDownloadbutton_Click(object sender, EventArgs e)
        {
            if (!FTPDownloadbackgroundWorker.IsBusy)
            {
                FTPDialog SettingsDialog = new FTPDialog();
                if (SettingsDialog.ShowDialog() == DialogResult.OK)
                {
                    StatuspictureBox.Image = FSD_2_Config_Editor.Properties.Resources.XeLove_Downloading_banner;
                    FTPDownloadbackgroundWorker.RunWorkerAsync();
                }
            }
        }

        private bool Download(string filePath, string fileName)
        {
            FtpWebRequest reqFTP = null;
            FileStream outputStream = null;
            FtpWebResponse response = null;
            Stream ftpStream = null;
            try
            {
                //filePath = <<The full path where the file is to be created. the>>, 
                //fileName = <<Name of the file to be createdNeed not name on FTP server. name name()>>
                
                outputStream = new FileStream(fileName, FileMode.Create);

                reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri("ftp://" + ftpServerIP + ":" + Port + DriveSelection + fileName));
                reqFTP.Method = WebRequestMethods.Ftp.DownloadFile;
                reqFTP.UseBinary = true;
                reqFTP.UsePassive = true;
                reqFTP.KeepAlive = false;
                reqFTP.Timeout = 20000;
                reqFTP.ReadWriteTimeout = 20000;
                reqFTP.Credentials = new NetworkCredential(ftpUserID, ftpPassword);
                
                response = (FtpWebResponse)reqFTP.GetResponse();
                
                ftpStream = response.GetResponseStream();
                long cl = response.ContentLength;
                int bufferSize = 4096;
                int readCount;
                byte[] buffer = new byte[bufferSize];

                readCount = ftpStream.Read(buffer, 0, bufferSize);
                while (readCount > 0)
                {
                    outputStream.Write(buffer, 0, readCount);
                    readCount = ftpStream.Read(buffer, 0, bufferSize);
                }

                ftpStream.Close();
                outputStream.Close();
                response.Close();
               
                return true;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                if (ftpStream != null)
                {
                    ftpStream.Close();
                }
                if (outputStream != null)
                {
                    outputStream.Close();
                }
                if (response != null)
                {
                    response.Close();
                }

                return false;
            }
            
        }

        private void OpenFile(string FileLocation)
        {
                    StreamReader Reader = new StreamReader(File.Open(FileLocation, FileMode.Open, FileAccess.Read), Encoding.UTF8);
                    
                    String Read;
                    Read = Reader.ReadToEnd();
                    Reader.Close();
                    if (Read.Contains("MUST be in GAME:\\"))
                    {
                        Read = Read.Replace("MUST be in GAME:\\", "");
                    }
                    if (Read.Contains("360Path='"))
                    {
                        Read = Read.Replace("360Path='", "TempPath='");
                    }

                    File.WriteAllText("temp", Read.ToString(), Encoding.UTF8);

                    XmlDocument xDoc = new XmlDocument();
                    xDoc.Load("temp");

                    XmlNodeList RegionNode = xDoc.GetElementsByTagName("locale");
                    XmlNodeList PathsNode = xDoc.GetElementsByTagName("paths");
                    XmlNodeList TimeNode = xDoc.GetElementsByTagName("timeformat");
                    XmlNodeList MoreOptionsNode = xDoc.GetElementsByTagName("moreoptions");
                    int p = 0;

                    for (int i = 0; i < PathsNode.Item(0).ChildNodes.Count; i++)
                    {
                        if (PathsNode.Item(0).ChildNodes.Item(i).NodeType.ToString() != "Comment")
                        {
                            Game[p].Path = PathsNode.Item(0).ChildNodes.Item(i).InnerText;
                            for (int l = 0; l < PathsNode.Item(0).ChildNodes.Item(i).Attributes.Count; l++)
                            {
                                if (PathsNode.Item(0).ChildNodes.Item(i).Attributes.Item(l).Name == "retail")
                                {
                                    Game[p].Retail = PathsNode.Item(0).ChildNodes.Item(i).Attributes.Item(l).Value;
                                }
                                else if (PathsNode.Item(0).ChildNodes.Item(i).Attributes.Item(l).Name == "devkit")
                                {
                                    Game[p].DevKit = PathsNode.Item(0).ChildNodes.Item(i).Attributes.Item(l).Value;
                                }
                            }
                            PathscomboBox.Items.Add(Game[p].Path);
                            p++;
                        }
                        NTP = Convert.ToInt32(TimeNode.Item(0).Attributes.Item(2).Value);
                        fanSpeed = Convert.ToInt32(MoreOptionsNode.Item(0).Attributes.Item(0).Value);
                        Region1 = RegionNode.Item(0).InnerText;

                        NTPcomboBox.SelectedIndex = NTP;
                        if (fanSpeed == 40)
                        {
                            FancomboBox.SelectedIndex = 0;
                        }
                        else
                        {
                            for (int l = 0; l < FancomboBox.Items.Count; l++)
                            {
                                if (FancomboBox.Items[l].ToString().Contains(fanSpeed.ToString()))
                                {
                                    FancomboBox.SelectedIndex = l;
                                    break;
                                }
                            }
                        }

                        for (int d = 0; d < RegioncomboBox.Items.Count; d++)
                        {
                            if (RegioncomboBox.Items[d].ToString().Contains(Region1))
                            {
                                RegioncomboBox.SelectedIndex = d;
                            }
                        }

                        groupBox2.Enabled = true;
                        groupBox3.Enabled = true;
                        groupBox4.Enabled = true;
                        groupBox7.Enabled = true;
                        Savebutton.Enabled = true;
                        Uploadbutton.Enabled = true;

                        if (File.Exists("temp"))
                        {
                            File.Delete("temp");
                        }
                    }
        }

        private void FTPDownloadbackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            if (Download("", "fsd2config.xml"))
            {
                DownloadComp = true;
            }
            else
            {
                DownloadComp = false;
            }
        }

        private void FTPDownloadbackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (DownloadComp == true)
            {
                OpenFile("fsd2config.xml");
               // File.Delete("fsd2config.xml");
                StatuspictureBox.Image = FSD_2_Config_Editor.Properties.Resources.XeLove_success_banner;
                timer1.Interval = 1500;
                timer1.Start();
            }
            else
            {
                
                StatuspictureBox.Image = FSD_2_Config_Editor.Properties.Resources.XeLove_banner;
            }

        }

        private void Uploadbutton_Click(object sender, EventArgs e)
        {
            if (!FTPUploadbackgroundWorker.IsBusy)
            {
                FTPDialog SettingsDialog = new FTPDialog();
                if (SettingsDialog.ShowDialog() == DialogResult.OK)
                {
                    WriteFile("fsd2config.xml");
                    StatuspictureBox.Image = FSD_2_Config_Editor.Properties.Resources.XeLove_uploading_banner;
                    FTPUploadbackgroundWorker.RunWorkerAsync();
                }
            }
        }
        private bool Upload(string filename)
        {
            FileInfo fileInf = null;
            FileStream fs = null;
            Stream strm = null;
            try
            {
                fileInf = new FileInfo(filename);
                string uri = "ftp://" + ftpServerIP  + ":" + Port + DriveSelection + fileInf.Name;
                FtpWebRequest reqFTP;

                reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(uri));
                reqFTP.Credentials = new NetworkCredential(ftpUserID, ftpPassword);

                reqFTP.KeepAlive = false;
                
                reqFTP.Method = WebRequestMethods.Ftp.UploadFile;
                reqFTP.UseBinary = true;
                reqFTP.UsePassive = true;

                reqFTP.ContentLength = fileInf.Length;

                // The buffer size is set to 2kb
                int buffLength = 4096;
                byte[] buff = new byte[buffLength];
                int contentLen;

                // Opens a file stream (System.IO.FileStream) to read the file to be uploaded
                fs = fileInf.OpenRead();
                // Stream to which the file to be upload is written
                strm = reqFTP.GetRequestStream();

                // Read from the file stream 2kb at a time
                contentLen = fs.Read(buff, 0, buffLength);

                // Till Stream content ends
                while (contentLen != 0)
                {
                    // Write Content from the file stream to the FTP Upload Stream
                    strm.Write(buff, 0, contentLen);
                    contentLen = fs.Read(buff, 0, buffLength);
                }

                // Close the file stream and the Request Stream
                strm.Close();
                fs.Close();
                return true;
            }
            catch (Exception ex)
            {
                if (strm != null)
                {
                    strm.Close();
                }
                if (fs != null)
                {
                    fs.Close();
                }
                MessageBox.Show(ex.Message, "Upload Error");
                return false;
            }
        }

        private void FTPUploadbackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            if (Upload("fsd2config.xml"))
            {
                UploadComp = true;
            }
            else
            {
                UploadComp = false;
            }
        }

        private void FTPUploadbackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (UploadComp == true)
            {
                StatuspictureBox.Image = FSD_2_Config_Editor.Properties.Resources.XeLove_success_banner;
                MessageBox.Show("Upload complete. Restart FSD2 for changes to take effect.", "Success", MessageBoxButtons.OK, MessageBoxIcon.Information);
                timer1.Interval = 1500;
                timer1.Start();
                File.Delete("fsd2config.xml");
            }
            else
            {
                MessageBox.Show("FAIL!");
            }
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            StatuspictureBox.Image = FSD_2_Config_Editor.Properties.Resources.XeLove_banner;
            timer1.Stop();
        }
    }
}
